// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <arpa/inet.h>
#include <cstring>
#include <fstream>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/timeb.h>
#include "VideoAgent.h"
#include "VideoEngine.h"
#include "VideoEncoder.h"
#include "HWSecure/include/securec.h"

namespace {
    const std::string LOG_LEVEL_INFO = "I";
    const std::string LOG_LEVEL_WARRING = "W";
    const std::string LOG_LEVEL_ERROR = "E";
    const std::string LOG_LEVEL_FATAL = "F";
    constexpr int  ARGC_LOCAL_PORT = 1;
    constexpr int  ARGC_ENCODER_TYPE = 2;
    constexpr int  ARGC_VIDEO_FRAME_TYPE = 3;
    constexpr int  ARGC_RESOLUTION = 4;
    constexpr int  ARGC_FPS = 5;
    constexpr int  ARGC_NUM = 6;
    constexpr int  ARGC_CAPTURE_IP = 3;
    constexpr int  MIN_ARGC = 4;
    constexpr int  ARGC_CHANEL = 5;
    constexpr int  ARGC_FRAMERATE = 6;
    constexpr int  ARGC_BITRATE = 7;
    constexpr int  LOG_LENGTH = 128;
}

std::ofstream fout;
int g_clientPort = 0;
std::string g_encoderType;
std::string g_videoFrameType;
std::string g_resolution;
std::string g_frameRate;

pid_t gettid(void)
{
    return (pid_t)syscall(__NR_gettid);
}

void HandleLog(const int level, const char* tag, const char* log)
{
    const char* logLevel = LOG_LEVEL_INFO.c_str();
    if (level == MIN_ARGC)
        logLevel = LOG_LEVEL_INFO.c_str();
    if(level == ARGC_CHANEL)
        logLevel = LOG_LEVEL_WARRING.c_str();
    if(level == ARGC_FRAMERATE)
        logLevel = LOG_LEVEL_ERROR.c_str();
    if(level == ARGC_BITRATE)
        logLevel = LOG_LEVEL_FATAL.c_str();
    int length = strlen(log);
    struct tm *pTm;
    struct timeb stTimeb;
    ftime(&stTimeb);
    pTm = localtime(&stTimeb.time);
    char logTarget[length + LOG_LENGTH];
    std::string fileName = "/var/log/worker/vss_" + std::to_string(g_clientPort) + ".log";
    if (!fout.is_open()) {
        fout.open(fileName.c_str(), std::ofstream::binary | std::ofstream::app | std::ofstream::out);
    }
    if (fout.is_open()) {
        (void)sprintf_s(logTarget, sizeof(logTarget),"[%02d-%02d %02d:%02d:%02d.%03d] [%d %d] %s %s" , \
               (pTm->tm_mon + ARGC_LOCAL_PORT), \
               pTm->tm_mday, \
               pTm->tm_hour, \
               pTm->tm_min, \
               pTm->tm_sec, \
               stTimeb.millitm,\
               (int)getpid(), \
               (int)gettid(), \
               logLevel, \
               log);
        fout.write(logTarget, strlen(logTarget));
        fout.write("\n",strlen("\n"));
    }
    fout.flush();
}

int main(int argc, char **argv)
{
    SetLogCallback(HandleLog);
    if (argc != ARGC_NUM) {
        ERR("Usage: %s <g_clientPort>", argv[0]);
        return 0;
    }
    g_clientPort = atoi(argv[ARGC_LOCAL_PORT]);
    g_encoderType = argv[ARGC_ENCODER_TYPE];
    g_videoFrameType = argv[ARGC_VIDEO_FRAME_TYPE];
    g_resolution = argv[ARGC_RESOLUTION];
    g_frameRate = argv[ARGC_FPS];
    if (!VideoAgent::GetInstance()->Init(g_clientPort, g_encoderType, g_videoFrameType, g_resolution, g_frameRate)) {
        ERR("VideoAgent init failed");
        VideoAgent::GetInstance()->DeInit();
        return 0;
    }
    VideoAgent::GetInstance()->AgentMainLoop();
    VideoAgent::GetInstance()->DeInit();
    fout.close();
    INFO("VideoAgent exit success");
    return 0;
}
